#include "Protocol.hpp"
#include "Sock.hpp"
using namespace std;

//版本2:
void Usage(std::string proc)
{
   cout << "Usage: " << proc << " port" << endl;
}
//线程的例程执行函数
void *HandlerRequest(void *args)
{
    int sock = *(int *)args;
    delete (int *)args;

    pthread_detach(pthread_self());//线程分离
    
    //实现业务逻辑
    //1.读取请求
    request_t req;//请求结构体
    char buffer[1024];
    ssize_t s = read(sock, buffer, sizeof(buffer) - 1); //读取序列化之后的请求
    if(s>0)
    {
        buffer[s] = 0; 
        cout << "get a new request(序列化): " << buffer << endl;
        std::string str = buffer;
        DeserializeRequest(str, req); //将请求进行反序列化

        cout << "request(反序列化): " << req.x << req.op << req.y << endl;//把请求打印出来
        //2.分析请求&&计算结果
        response_t resp = {0, 0};//响应结构体
        switch (req.op)
        {
        case '+':
            resp.result = req.x + req.y;
            break;
        case '-':
            resp.result = req.x - req.y;
            break;
        case '*':
            resp.result = req.x * req.y;
            break;
        case '/':
            if (req.y == 0)
                resp.code = -1; //代表除0错误,此时result是多少已经没所谓了
            else
                resp.result = req.x / req.y;
            break;
        case '%':
            if (req.y == 0)
                resp.code = -2; //代表模0错误
            else
                resp.result = req.x % req.y;
            break;
        default:
            resp.code = -3; //代表请求方法异常 不是+-/*%
            break;
        }
        //4.构建响应，并进行返回
        std::string send_string = SerializeResponse(resp);   //把响应进行序列化,发送给客户端
        write(sock, send_string.c_str(),send_string.size());     
        cout << "服务结束,收到的请求是: " << send_string << endl;
    }

    
    //5.关闭链接
    close(sock);
}



//之后我们是这样启动服务端的: ./CalServer 服务端的port
int main(int argc,char* argv[])
{   
    if(argc!=2)
    {
        Usage(argv[0]);
        exit(1);
    }
    //1.创建套接字
    int listen_sock = Sock::Socket();
    //2.将套接字绑定服务器
    uint16_t port = atoi(argv[1]);//服务端的端口号
    Sock::Bind(listen_sock,port);
    //3.设置套接字为监听状态
    Sock::Listen(listen_sock);
 
    for(;;)
    {
        int new_sock = Sock::Accept(listen_sock);//从套接字中获取链接
        if(new_sock>=0)
        {
            //创建新线程对请求做处理
            cout << "get a new client..." << endl;
            int *pram = new int(new_sock);//当前accpet返回的套接字信息
            pthread_t tid;
            //在线程的例程函数中执行线程分离,后序就不需要我们等待这个线程了
            pthread_create(&tid, nullptr, HandlerRequest, pram);
        }        
    }
    return 0;
}

/*
void Usage(std::string proc)
{
   cout << "Usage: " << proc << " port" << endl;
}
//版本1:无序列化和反序列化
//线程的例程执行函数
void *HandlerRequest(void *args)
{
    int sock = *(int *)args;
    delete (int *)args;

    pthread_detach(pthread_self());//线程分离
    
    //实现业务逻辑
    //1.读取请求
    request_t req;//请求结构体
    ssize_t s = read(sock,&req,sizeof(req));//读取请求
    cout << "request: " << req.x << req.op << req.y << endl;//把请求打印出来
    if(s == sizeof(req)) //读取到了完整的请求
    {
        //2.分析请求&&计算结果
        response_t resp = {0, 0};//响应结构体
        switch (req.op)
        {
        case '+':
            resp.result = req.x + req.y;
            break;
        case '-':
            resp.result = req.x - req.y;
            break;
        case '*':
            resp.result = req.x * req.y;
            break;
        case '/':
            if (req.y == 0)
                resp.code = -1; //代表除0错误,此时result是多少已经没所谓了
            else
                resp.result = req.x / req.y;
            break;
        case '%':
            if (req.y == 0)
                resp.code = -2; //代表模0错误
            else
                resp.result = req.x % req.y;
            break;
        default:
            resp.code = -3; //代表请求方法异常 不是+-/*%
            break;
        }

        //4.构建响应，并进行返回
        write(sock, &resp, sizeof(resp));//把响应写回
        cout <<"本轮服务结束~~~~~~~"<<endl;
    }
    //5.关闭链接
    close(sock);
}



//之后我们是这样启动服务端的: ./CalServer 服务端的port
int main(int argc,char* argv[])
{   
    if(argc!=2)
    {
        Usage(argv[0]);
        exit(1);
    }
    //1.创建套接字
    int listen_sock = Sock::Socket();
    //2.将套接字绑定服务器
    uint16_t port = atoi(argv[1]);//服务端的端口号
    Sock::Bind(listen_sock,port);
    //3.设置套接字为监听状态
    Sock::Listen(listen_sock);
 
    for(;;)
    {
        int new_sock = Sock::Accept(listen_sock);//从套接字中获取链接
        if(new_sock>=0)
        {
            //创建新线程对请求做处理
            cout << "get a new client..." << endl;
            int *pram = new int(new_sock);//当前accpet返回的套接字信息
            pthread_t tid;
            //在线程的例程函数中执行线程分离,后序就不需要我们等待这个线程了
            pthread_create(&tid, nullptr, HandlerRequest, pram);
        }        
    }
    return 0;
}
*/